<template>
  <!-- 权限检查：只有指定账号才能访问 -->
  <div v-if="!hasPermission" class="permission-denied">
    <div class="permission-content">
      <div class="permission-icon">🔒</div>
      <h2 class="permission-title">访问受限</h2>
      <p class="permission-message">此页面仅限特定账号访问</p>
      <div class="permission-actions">
        <a-button v-if="!userStore.isAuthenticated" type="primary" @click="openLoginDialog"> 登录账号 </a-button>
        <a-button v-else @click="goBack"> 返回上页 </a-button>
      </div>
    </div>
  </div>

  <!-- 添加图表页面容器 -->
  <div v-else class="add-page">
    <!-- 页面头部区域 -->
    <div class="add-page-header">
      <h1 class="add-page-title">添加图表</h1>
    </div>

    <!-- 页面主体内容区域 -->
    <div class="add-page-content">
      <!-- 左侧表单区域 -->
      <div class="add-page-form">
        <!-- 图表名称输入区域 -->
        <div class="add-page-form-item">
          <div class="form-item-header">
            <label class="add-page-form-label">
              图表名称
              <span class="required-mark">*</span>
            </label>
            <button class="add-page-submit" @click="handleSubmit">保存</button>
          </div>
          <input v-model="chartForm.name" type="text" class="add-page-form-input" :class="{ 'is-error': showError && !chartForm.name }" placeholder="请输入图表名称" />
          <div class="error-tip" v-if="showError && !chartForm.name">请输入图表名称</div>
        </div>

        <!-- 图表描述输入区域 -->
        <div class="add-page-form-item">
          <label class="add-page-form-label">
            图表描述
            <span class="required-mark">*</span>
          </label>
          <textarea v-model="chartForm.description" class="add-page-form-textarea" :class="{ 'is-error': showError && !chartForm.description }" placeholder="请输入图表描述"></textarea>
          <div class="error-tip" v-if="showError && !chartForm.description">请输入图表描述</div>
        </div>

        <!-- 图表类型选择区域 -->
        <div class="add-page-form-item">
          <label class="add-page-form-label">
            图表类型
            <span class="required-mark">*</span>
          </label>
          <div class="chart-select" v-click-outside="closeSelect" :aria-expanded="isSelectOpen">
            <div class="chart-select-input" :class="{ 'is-error': showError && !chartForm.type }" @click="toggleSelect">
              <span class="chart-select-label">{{ selectedLabel }}</span>
              <div class="chart-select-arrow"></div>
            </div>
            <div class="error-tip" v-if="showError && !chartForm.type">请选择图表类型</div>
            <transition name="slide-fade">
              <div class="chart-select-dropdown" v-show="isSelectOpen">
                <div v-for="type in chartMenus" :key="type.value" class="chart-select-option" :class="{ 'is-active': chartForm.type === type.value }" @click="selectOption(type)">
                  <i :class="[type.icon, 'chart-select-icon']"></i>
                  <span>{{ type.label }}</span>
                </div>
              </div>
            </transition>
          </div>
        </div>

        <!-- 图表标签选择区域 -->
        <div class="add-page-form-item">
          <label class="add-page-form-label">图表标签</label>
          <div class="add-page-form-tags">
            <div v-for="tag in chartTags" :key="tag" class="add-page-form-tag" :class="{ 'is-active': chartForm.tags.includes(tag) }" @click="toggleTag(tag)">
              {{ tag }}
            </div>
          </div>
        </div>

        <!-- 图表预览区域 -->
        <div class="add-page-chart">
          <div class="add-page-chart-header">
            <span class="add-page-chart-title">预览效果</span>
          </div>
          <div class="add-page-chart-content" id="chart-container"></div>
        </div>
      </div>

      <!-- 右侧代码编辑和预览区域 -->
      <div class="add-page-preview">
        <div class="add-page-editor">
          <div class="add-page-editor-header">
            <div class="editor-title-wrap">
              <span class="add-page-editor-title">配置代码</span>
              <transition name="fade">
                <div class="code-error-tip" v-if="codeError" @click="clearCodeError">
                  <span class="code-error-icon">⚠️</span>
                  <span class="code-error-message">{{ codeError }}</span>
                  <span class="code-error-close">×</span>
                </div>
              </transition>
            </div>
            <button class="add-page-chart-run" @click="runChart">运行</button>
          </div>
          <div class="add-page-editor-content" id="monaco-editor"></div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import './index.css'
import { ref, onMounted, nextTick, computed, onUnmounted, watch } from 'vue'
import * as monaco from 'monaco-editor'
import * as echarts from 'echarts'
import 'echarts-gl'
import 'echarts-liquidfill'
import $ from 'jquery'
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
import { chartMenus } from '@/utils/chartTypes'
import html2canvas from 'html2canvas'
import { uploadImg, addChart } from '@/utils/api'
import { useUserStore } from '@/stores/user'
import { useRouter } from 'vue-router'
import { message } from 'ant-design-vue'

// 使用用户状态管理和路由
const userStore = useUserStore()
const router = useRouter()

// 访问权限控制
const ALLOWED_USERNAME = 'woaichitudouo'

/**
 * 检查用户是否有访问权限
 * 只有登录且用户名为指定账号的用户才能访问
 */
const hasPermission = computed(() => {
  return userStore.isAuthenticated && userStore.username === ALLOWED_USERNAME
})

/**
 * 打开登录对话框
 * 通过派发自定义事件通知App.vue组件
 */
const openLoginDialog = () => {
  // 派发自定义事件到全局，让App.vue监听并打开登录对话框
  window.dispatchEvent(new CustomEvent('openLogin'))
}

/**
 * 返回上一页
 */
const goBack = () => {
  router.back()
}

// 配置 Monaco Editor 的 Web Worker
self.MonacoEnvironment = {
  getWorker(_, label) {
    // 根据不同的文件类型返回对应的 Worker
    if (label === 'json') return new jsonWorker()
    if (label === 'css' || label === 'scss' || label === 'less') return new cssWorker()
    if (label === 'html' || label === 'handlebars' || label === 'razor') return new htmlWorker()
    if (label === 'typescript' || label === 'javascript') return new tsWorker()
    return new editorWorker()
  }
}

// 图表配置表单数据
const chartForm = ref({
  name: '', // 图表名称
  description: '', // 图表描述
  type: 'line', // 图表类型
  tags: ['基础'] // 图表标签
})

// 预定义的图表标签选项
const chartTags = ['基础', '动画', '交互', '响应式', '数据集', 'GL', '地理', '统计']

// Monaco Editor 实例
let editor = null
// ECharts 实例
let chart = null

/**
 * 切换标签选中状态
 * @param {string} tag - 要切换的标签名称
 */
const toggleTag = (tag) => {
  const index = chartForm.value.tags.indexOf(tag)
  if (index > -1) {
    chartForm.value.tags.splice(index, 1)
  } else {
    chartForm.value.tags.push(tag)
  }
}

// 表单验证状态
const showError = ref(false)

/**
 * 验证表单
 * @returns {boolean} - 返回验证结果
 */
const validateForm = () => {
  if (!chartForm.value.name || !chartForm.value.description || !chartForm.value.type) {
    showError.value = true
    return false
  }
  showError.value = false
  return true
}

// 代码错误状态
const codeError = ref('')

/**
 * 运行图表配置代码
 * 支持异步数据加载和3D图表配置
 */
const runChart = () => {
  try {
    codeError.value = '' // 清除之前的错误
    const code = editor.getValue()
    if (!code.trim()) {
      codeError.value = '请输入图表配置代码'
      return
    }

    // 移除之前的错误监听器
    window._removeErrorListener?.()
    window._removeRejectionListener?.()

    // 添加全局错误处理
    const errorHandler = (event) => {
      if (event.error) {
        codeError.value = `运行错误: ${event.error.message || '未知错误'}`
        event.preventDefault()
      }
    }

    const rejectionHandler = (event) => {
      codeError.value = `运行错误: ${event.reason?.message || event.reason || '未知错误'}`
      event.preventDefault()
    }

    window.addEventListener('error', errorHandler)
    window.addEventListener('unhandledrejection', rejectionHandler)

    // 保存移除监听器的函数
    window._removeErrorListener = () => window.removeEventListener('error', errorHandler)
    window._removeRejectionListener = () => window.removeEventListener('unhandledrejection', rejectionHandler)

    // 检查代码是否包含异步操作或3D图表配置
    if (code.includes('$.get(') || code.includes('fetch(') || code.includes('grid3D')) {
      // 异步执行代码
      const fn = new Function(
        'echarts',
        'jQuery',
        'myChart',
        'nextTick',
        `
        const $ = jQuery;
        
        // 处理地图数据加载
        function loadMapData(url) {
          return new Promise((resolve, reject) => {
            $.get(url, function(data) {
              resolve(data);
            }).fail(function(error) {
              reject(error);
            });
          });
        }

        // 包装执行代码
        async function executeChart() {
          try {
            ${code}
            if (typeof option === 'undefined') {
              throw new Error('图表配置无效：option 未定义');
            }
            return option;
          } catch (error) {
            throw error;
          }
        }

        // 在 nextTick 中执行
        nextTick(async () => {
          try {
            const option = await executeChart();
            if (option) {
              nextTick(() => {
                myChart.setOption(option, true);
              });
            }
          } catch (error) {
            throw error;
          }
        });
      `
      )

      fn(echarts, $, chart, nextTick)
    } else {
      // 同步执行简单配置
      const fn = new Function(
        'echarts',
        'jQuery',
        'myChart',
        'nextTick',
        `
        const $ = jQuery;
        
        function executeChart() {
          try {
            ${code}
            if (typeof option === 'undefined') {
              throw new Error('图表配置无效：option 未定义');
            }
            return option;
          } catch (error) {
            throw error;
          }
        }

        nextTick(() => {
          try {
            const option = executeChart();
            if (option) {
              nextTick(() => {
                myChart.setOption(option, true);
              });
            }
          } catch (error) {
            throw error;
          }
        });
      `
      )

      fn(echarts, $, chart, nextTick)
    }
  } catch (error) {
    console.error('图表配置错误:', error)
    codeError.value = `运行错误: ${error.message || '未知错误'}`
  }
}

// 组件卸载时清理错误监听器
onUnmounted(() => {
  window._removeErrorListener?.()
  window._removeRejectionListener?.()
})

// 清除代码错误提示
const clearCodeError = () => {
  codeError.value = ''
}

/**
 * 初始化 ECharts 实例
 */
const initChart = () => {
  const container = document.getElementById('chart-container')
  if (!container) return

  // 初始化 ECharts 实例
  chart = echarts.init(container, null, {
    renderer: 'canvas',
    useDirtyRect: false
  })

  // 设置容器尺寸
  container.style.width = '100%'
  container.style.height = '100%'
  container.style.minHeight = '580px'
  container.style.minWidth = '524px'

  chart.resize()
}

// 监听用户登录状态变化，进行权限检查
watch(
  () => userStore.isAuthenticated,
  (newAuth) => {
    if (newAuth && userStore.username !== ALLOWED_USERNAME) {
      // 用户登录了但不是指定账号
      message.warning('此页面仅限特定账号访问')
    }
  },
  { immediate: true }
)

// 监听用户名变化
watch(
  () => userStore.username,
  (newUsername) => {
    if (userStore.isAuthenticated && newUsername !== ALLOWED_USERNAME) {
      message.warning('此页面仅限特定账号访问')
    }
  }
)

// 编辑器默认代码
const defaultCode = `option = {
  
};`

/**
 * 定义 Monokai 主题
 */
const defineMonokaiTheme = () => {
  monaco.editor.defineTheme('monokai', {
    base: 'vs-dark',
    inherit: true,
    rules: [
      { token: '', foreground: 'F8F8F2', background: '272822' },
      { token: 'comment', foreground: '75715E', fontStyle: 'italic' },
      { token: 'keyword', foreground: 'F92672', fontStyle: 'bold' },
      { token: 'keyword.operator', foreground: 'F92672' },
      { token: 'string', foreground: 'E6DB74' },
      { token: 'string.escape', foreground: 'AE81FF' },
      { token: 'number', foreground: 'AE81FF' },
      { token: 'regexp', foreground: 'FD971F' },
      { token: 'type', foreground: '66D9EF', fontStyle: 'italic' },
      { token: 'variable', foreground: 'F8F8F2' },
      { token: 'variable.parameter', foreground: 'FD971F', fontStyle: 'italic' },
      { token: 'entity.name.function', foreground: 'A6E22E' },
      { token: 'entity.name.class', foreground: 'A6E22E', fontStyle: 'underline' },
      { token: 'entity.name.type', foreground: '66D9EF', fontStyle: 'italic' },
      { token: 'entity.other.attribute-name', foreground: 'A6E22E' },
      { token: 'entity.other.attribute-name.class', foreground: 'A6E22E', fontStyle: 'underline' },
      { token: 'entity.other.attribute-name.id', foreground: 'A6E22E', fontStyle: 'underline' },
      { token: 'meta.tag', foreground: 'F8F8F2' },
      { token: 'meta.tag.sgml', foreground: 'F8F8F2' },
      { token: 'meta.selector', foreground: 'F92672' },
      { token: 'entity.name.tag', foreground: 'F92672' },
      { token: 'punctuation.definition.tag.html', foreground: 'F8F8F2' },
      { token: 'punctuation.definition.tag.begin.html', foreground: 'F8F8F2' },
      { token: 'punctuation.definition.tag.end.html', foreground: 'F8F8F2' }
    ],
    colors: {
      'editor.background': '#272822',
      'editor.foreground': '#F8F8F2',
      'editorCursor.foreground': '#F8F8F0',
      'editor.lineHighlightBackground': '#3E3D32',
      'editorLineNumber.foreground': '#90908A',
      'editor.selectionBackground': '#49483E',
      'editor.inactiveSelectionBackground': '#49483E',
      'editorWhitespace.foreground': '#3B3A32',
      'editorIndentGuide.background': '#3B3A32',
      'editorIndentGuide.activeBackground': '#9D550FB0',
      'editor.selectionHighlightBorder': '#222218',
      'editorSuggestWidget.background': '#272822',
      'editorSuggestWidget.border': '#3E3D32',
      'editorSuggestWidget.foreground': '#F8F8F2',
      'editorSuggestWidget.highlightForeground': '#F92672',
      'editorSuggestWidget.selectedBackground': '#414339',
      'editorHoverWidget.background': '#272822',
      'editorHoverWidget.border': '#3E3D32'
    }
  })
}

/**
 * 初始化 Monaco Editor
 */
const initEditor = () => {
  const container = document.getElementById('monaco-editor')
  if (!container) return

  // 定义主题
  defineMonokaiTheme()

  editor = monaco.editor.create(container, {
    value: defaultCode,
    language: 'javascript',
    theme: 'monokai',
    automaticLayout: true,
    fontSize: 21,
    lineHeight: 23,
    minimap: {
      enabled: false
    },
    fontFamily: 'Consolas, Monaco, monospace',
    fontWeight: '400',
    letterSpacing: 0.5
  })
}

// 图表类型选择相关状态
const isSelectOpen = ref(false)
const selectedLabel = computed(() => {
  const selected = chartMenus.find((item) => item.value === chartForm.value.type)
  return selected?.label || ''
})

// 切换选择器显示状态
const toggleSelect = () => {
  isSelectOpen.value = !isSelectOpen.value
}

// 关闭选择器
const closeSelect = () => {
  isSelectOpen.value = false
}

// 选择图表类型
const selectOption = (type) => {
  chartForm.value.type = type.value
  isSelectOpen.value = false
}

// 点击外部关闭指令
const vClickOutside = {
  mounted(el, binding) {
    el._clickOutside = (event) => {
      if (!(el === event.target || el.contains(event.target))) {
        binding.value(event)
      }
    }
    document.addEventListener('click', el._clickOutside)
  },
  unmounted(el) {
    document.removeEventListener('click', el._clickOutside)
  }
}

/**
 * 获取图表预览区域的截图
 * @returns {Promise<string>} base64格式的图片数据
 */
const getChartScreenshot = async () => {
  const container = document.getElementById('chart-container')
  if (!container) {
    throw new Error('找不到图表容器')
  }

  // 等待图表完全渲染
  await nextTick()

  const canvas = await html2canvas(container, {
    backgroundColor: null,
    useCORS: true,
    scale: 2, // 提高截图质量
    logging: false
  })

  // 检查画布是否为空
  const context = canvas.getContext('2d')
  const imageData = context.getImageData(0, 0, canvas.width, canvas.height)
  const pixels = imageData.data

  // 检查是否所有像素都是透明的
  let hasContent = false
  for (let i = 3; i < pixels.length; i += 4) {
    if (pixels[i] !== 0) {
      // 检查 alpha 通道
      hasContent = true
      break
    }
  }

  if (!hasContent) {
    throw new Error('图表预览内容为空，请先运行有效的图表代码')
  }

  return canvas.toDataURL('image/png')
}

/**
 * 显示消息提示
 * @param {string} message - 提示消息
 * @param {string} type - 提示类型 success | error
 */
const showMessage = (message, type = 'success') => {
  const messageEl = document.createElement('div')
  messageEl.className = `message message-${type}`
  messageEl.textContent = message
  document.body.appendChild(messageEl)

  // 添加显示动画
  setTimeout(() => {
    messageEl.classList.add('message-show')
  }, 10)

  // 3秒后移除
  setTimeout(() => {
    messageEl.classList.remove('message-show')
    setTimeout(() => {
      document.body.removeChild(messageEl)
    }, 300)
  }, 3000)
}

/**
 * 显示加载中
 * @param {string} text - 加载提示文字
 * @returns {Function} 关闭loading的函数
 */
const showLoading = (text = '加载中...') => {
  const loadingEl = document.createElement('div')
  loadingEl.className = 'loading-mask'
  loadingEl.innerHTML = `
    <div class="loading-spinner"></div>
    <div class="loading-text">${text}</div>
  `
  document.body.appendChild(loadingEl)

  // 添加显示动画
  setTimeout(() => {
    loadingEl.classList.add('loading-show')
  }, 10)

  // 返回关闭函数
  return () => {
    loadingEl.classList.remove('loading-show')
    setTimeout(() => {
      document.body.removeChild(loadingEl)
    }, 300)
  }
}

/**
 * 处理表单提交
 * 提交图表配置信息到服务器
 */
const handleSubmit = async () => {
  // 表单验证
  if (!validateForm()) {
    return
  }

  // 检查是否有图表预览
  const container = document.getElementById('chart-container')
  if (!container || !container.children.length) {
    showMessage('请先运行预览图表', 'error')
    return
  }

  // 显示loading
  const closeLoading = showLoading('正在保存...')

  // 获取编辑器中的代码
  const code = editor.getValue()

  // 获取图表截图
  const screenshot = await getChartScreenshot().catch((error) => {
    showMessage(error.message, 'error')
    closeLoading()
    return null
  })

  if (!screenshot) return

  // 生成随机文件名
  const timestamp = Date.now()
  const random = Math.floor(Math.random() * 10000)
  const filename = `img_${timestamp}_${random}.png`

  // 将base64转换为File对象
  const base64Data = screenshot.split(',')[1]
  const binaryData = atob(base64Data)
  const array = new Uint8Array(binaryData.length)
  for (let i = 0; i < binaryData.length; i++) {
    array[i] = binaryData.charCodeAt(i)
  }
  const blob = new Blob([array], { type: 'image/png' })
  const file = new File([blob], filename, { type: 'image/png' })

  // 创建FormData对象
  const formData = new FormData()
  formData.append('file', file)

  // 上传文件
  const uploadResult = await uploadImg(formData).catch((error) => {
    showMessage('图片上传失败', 'error')
    closeLoading()
    return null
  })

  if (!uploadResult) return

  // 构建提交的数据
  const submitData = {
    name: chartForm.value.name,
    description: chartForm.value.description,
    type: chartForm.value.type,
    tags: chartForm.value.tags,
    previewUrl: uploadResult.data.filename,
    codeSnippet: code
  }

  // 发送请求保存图表
  const response = await addChart(submitData).catch((error) => {
    showMessage('保存图表失败', 'error')
    closeLoading()
    return null
  })

  if (!response) return

  if (response.code === 200) {
    showMessage('保存成功')

    // 清空表单
    chartForm.value = {
      name: '',
      description: '',
      type: '',
      tags: []
    }

    // 重置编辑器内容
    editor.setValue(defaultCode)

    // 清除图表预览
    chart.clear()
    chart.setOption({})

    // 跳转到图表列表页
    // router.push('/charts')
  } else {
    showMessage(response.message || '保存失败', 'error')
  }

  closeLoading()
}

// 组件挂载后初始化
onMounted(() => {
  // 只有在有权限的情况下才初始化编辑器和图表
  if (hasPermission.value) {
    // 给一个短暂的延时确保 DOM 已经渲染
    setTimeout(() => {
      initEditor()
      initChart()
    }, 100)
  }
})

// 监听权限变化，当获得权限时初始化
watch(hasPermission, (newPermission) => {
  if (newPermission) {
    // 获得权限时初始化编辑器和图表
    nextTick(() => {
      setTimeout(() => {
        initEditor()
        initChart()
      }, 100)
    })
  }
})
</script>
